/* eslint-disable no-undef */
import Logger from "../base/logger";
import {
    IvcsError
} from "../base/error";
import {
    isEmptyString,
    isJsonString,
    logObject
} from './tool';

/**
 * 登录
 * @param {string} url 登录url
 * @param {object} para body参数
 * @returns Promise.<object, Error>
 */
export const login = (url, para) => {
    if (typeof navigator == "undefined" && typeof wx !== "undefined" && wx.request) {
        return new Promise((resolve, reject) => {
            wx.request({
                url: url + '/ivcs/api/v1/auth/logon',
                data: para,
                method: 'post',
                header: {
                    'content-type': 'application/json'
                },
                fail(error) {
                    reject(error);
                },
                success(res) {
                    resolve(res);
                }
            })
        })
    }
}

/**
 * token失效，重新刷新链接
 * @param {string} url 访问url
 * @param {object} para body参数
 * @returns Promise.<object, Error>
 */
export const refreshToken = (url, para) => {
    if (typeof navigator == "undefined" && typeof wx !== "undefined" && wx.request) {
        return new Promise((resolve, reject) => {
            wx.request({
                url: url + '/ivcs/api/v1/auth/refresh-token',
                data: para,
                method: 'post',
                header: {
                    'content-type': 'application/json'
                },
                fail(error) {
                    reject(error);
                },
                success(res) {
                    resolve(res);
                }
            })
        })
    }
}

/**
 * 创建一个有时长的token，用来鉴权推拉流在rtmp server
 * @param {string} url 请求的url
 * @param {string} token 登录之后返回的用户信息token
 * @param {number} validityTime 有效时长，默认是30分钟
 * @returns Promise.<object, Error>
 */
export const createRtmpServerTokenWithValidityTime = (url, token, validityTime) => {
    if (typeof navigator == "undefined" && typeof wx !== "undefined" && wx.request) {
        return new Promise((resolve, reject) => {
            wx.request({
                url: url + '/ivcs/api/v1/oneTimeToken',
                data: {
                    validityTime: validityTime
                },
                method: 'post',
                header: {
                    'content-type': 'application/json',
                    'x-access-token': token
                },
                fail(error) {
                    reject(error);
                },
                success(res) {
                    resolve(res);
                }
            })
        })
    }
}

/**
 * 小程序把rtmp流推送到zms
 * @param {string} backendUrl 后台url
 * @param {string} roomId 房间id
 * @param {string} owner joinroom后返回的selfId
 * @param {string} url rtmp流的url
 * @param {object} attributes 推到zms后的forward流的属性,可自定义 如{type:'customer'}
 * @returns Promise.<object, Error>
 */
export const streamingIns = (backendUrl, roomId, owner, url, attributes = {}) => {
    let para = {
        "url": url,
        "media": {
            "audio": "auto",
            "video": true
        },
        "transport": {
            "protocol": "tcp",
            "bufferSize": 4096
        },
        "owner": owner,
        "attributes": attributes
    }
    let requestUrl = backendUrl + '/ivcs/api/v1/rooms/' + roomId + '/streaming-ins';
    if (typeof navigator == "undefined" && typeof wx !== "undefined" && wx.request) {
        return new Promise((resolve, reject) => {
            wx.request({
                url: requestUrl,
                data: para,
                method: 'post',
                header: {
                    'content-type': 'application/json'
                },
                fail(error) {
                    reject(error);
                },
                success(res) {
                    resolve(res);
                }
            })
        })
    }
}

/**
 * 把流推送到外流媒体服务，如rtmp
 * @param {string} url 服务的地址
 * @param {string} roomId 房间id
 * @param {object} para body参数
 * @returns Promise.<object, Error>
 */
export const streamOuts = (url, roomId, para) => {
    let requestUrl = url + '/ivcs/api/v1/rooms/' + roomId + '/streaming-outs';
    if (typeof navigator == "undefined" && typeof wx !== "undefined" && wx.request) {
        return new Promise((resolve, reject) => {
            wx.request({
                url: requestUrl,
                data: para,
                method: 'post',
                header: {
                    'content-type': 'application/json'
                },
                fail(error) {
                    reject(error);
                },
                success(res) {
                    resolve(res);
                }
            })
        })
    }
}

/**
 * 获取当前rtmp server上的所有的rtmp流
 * @param {string} url 后台url
 * @param {string} token accesstoken
 */
export const getStat = (url, token) => {
    let requestUrl = url + '/ivcs/api/v1/private/rtmp/stat';
    if (typeof navigator == "undefined" && typeof wx !== "undefined" && wx.request) {
        return new Promise((resolve, reject) => {
            wx.request({
                url: requestUrl,
                method: 'GET',
                dataType: 'json',
                responseType: 'text',
                header: {
                    'content-type': 'application/json',
                    'x-access-token': token
                },
                success: function (res) {
                    resolve(res);
                },
                fail: function (error) {
                    reject(error);
                }
            })
        })
    }
}

/**
 * 把流加入到mix流中
 * @param {string} url 访问的url
 * @param {string} roomId 房间id
 * @param {string} streamId 流id
 * @param {string} token 鉴权的token
 * @returns Promise.<object, Error>
 */
export const addStreamToMix = (url, roomId, streamId, token) => {
    if (typeof navigator == "undefined" && typeof wx !== "undefined" && wx.request) {
        return new Promise((resolve, reject) => {
            wx.request({
                url: url + '/ivcs/api/v1/rooms/' + roomId + '/streams/' + streamId,
                data: [{
                    "op": "add",
                    "path": "/info/inViews",
                    "value": "common"
                }],
                method: 'patch',
                header: {
                    'content-type': 'application/json',
                    'x-access-token': token
                },
                fail(error) {
                    reject(error);
                },
                success(res) {
                    resolve(res);
                }
            })
        })
    }
}

/**
 * 将某一个流加入到mix流中
 * @param {string} backendUrl 访问url
 * @param {string} roomId 房间id
 * @param {string} streamId 流id
 * @param {string} accessToken 鉴权token
 * @param {boolean} needThrownException 是否需要留痕异常
 */
export async function addStreamToMixStream(backendUrl, roomId, streamId, accessToken, needThrownException = false) {
    return await new Promise((resolve, reject) => {
        let requestUrl = backendUrl + '/ivcs/api/v1/rooms/' + roomId + '/streams/' + streamId;
        addStreamToMix(backendUrl, roomId, streamId, accessToken).then((resp) => {
            // Logger.info(`add stream to mix success,${streamId},${JSON.stringify(resp)},${new Date()}`);
            logWithRequestResponse(requestUrl, resp, null, true);
            resolve();
        }).catch((error) => {
            //Logger.info(`add stream to mix failed,${streamId},${error},${JSON.stringify(error.response)},${new Date()}`);
            logWithRequestResponse(requestUrl, null, error, true);
            if (needThrownException) {
                let response = new IvcsError('4002', logWithRequestResponse(requestUrl, null, error, false));
                reject(response);
            } else {
                resolve();
            }
        });
    });
}

/**
 * 小程序把rtmp流推送到zms
 * @param {string} backendUrl 后台url
 * @param {string} roomId 房间id
 * @param {string} owner joinroom后返回的selfId
 * @param {string} url rtmp流的url
 * @param {object} attributes 推到zms后的forward流的属性,可自定义 如{type:'customer'}
 * @param {boolean} needThrownException 是否需要留痕异常
 * @returns Promise.<string, Error> 流id
 */
export async function pushRtmpUrlToZms(backendUrl, roomId, owner, url, attributes, needThrownException = false) {
    return await new Promise((resolve, reject) => {
        let requestUrl = backendUrl + '/ivcs/api/v1/rooms/' + roomId + '/streaming-ins';
        streamingIns(backendUrl, roomId, owner, url, attributes).then((resp) => {
            if (resp && resp.data && resp.data.id) {
                resolve(resp.data.id);
            } else {
                if (needThrownException) {
                    let response = new IvcsError('4010', logWithRequestResponse(requestUrl, null, error, false));
                    reject(response);
                } else {
                    resolve(null);
                }
            }
        }).catch((error) => {
            if (needThrownException) {
                let response = new IvcsError('4010', logWithRequestResponse(requestUrl, null, error, false));
                reject(response);
            } else {
                resolve(null);
            }
        })
    });
}

/**
 * 判断一个rtmp url 是否推流成功
 * @param {string} backendUrl 后台地址
 * @param {string} accessToken accesstoken
 * @param {string} rtmpUrlPath live-pusher推流的地址路径 如rtmp://161.189.61.223/liveshow/12345678  则rtmpUrlPath为12345678
 * @returns Promise.<boolean, Error>
 */
export async function getRtmpStat(backendUrl, accessToken, rtmpUrlPath) {
    return await new Promise((resolve, reject) => {
        let requestUrl = backendUrl + '/ivcs/api/v1/private/rtmp/stat';
        getStat(backendUrl, accessToken).then((resp) => {
            Logger.info('ivcs-js-sdk:getrtmpstat', rtmpUrlPath, resp.data);
            logWithRequestResponse(requestUrl, resp, null, true);
            if (resp.data && resp.data.includes(rtmpUrlPath)) {
                resolve(true);
            } else {
                reject(false);
            }
        }).catch((error) => {
            logWithRequestResponse(requestUrl, null, error, true);
            reject(false);
        });
    });
}

/**
 * 小程序订阅机器人的流
 * @param {string} url 访问的后台url
 * @param {string} roomId 房间id
 * @param {string} owner 加入房间后的participantId
 * @param {string} robotRtmpUrl 坐席的流rtmp地址
 */
export async function subscribeRobotStream(url, roomId, owner, robotRtmpUrl) {
    return await new Promise((resolve, reject) => {
        let para = {
            "media": {
                "audio": {
                    "from": roomId + '-common'
                },
                "video": {
                    "from": roomId + '-common'
                }
            },
            "url": robotRtmpUrl,
            "owner": owner,
            "protocol": "rtmp"
        };
        let requestUrl = url + '/ivcs/api/v1/rooms/' + roomId + '/streaming-outs';
        streamOuts(url, roomId, para).then((resp) => {
            logWithRequestResponse(requestUrl, resp, null, true);
            if (resp.data) {
                resolve(resp);
            } else {
                let response = new IvcsError('4006', logWithRequestResponse(requestUrl, resp, null, false));
                reject(response);
            }
        }).catch((error) => {
            logWithRequestResponse(requestUrl, null, error, true);
            let response = new IvcsError('4006', logWithRequestResponse(requestUrl, null, error, false));
            reject(response);
        });
    });
}

/**
 * 创建一个有时长的token，用来鉴权推拉流在rtmp server
 * @param {string} url 请求的url
 * @param {string} token 登录之后返回的用户信息token
 * @param {number} validityTime 有效时长，默认是30分钟
 * @returns Promise.<object, Error>
 */
export async function createTokenWithRtmpServer(url, token, validityTime) {
    return await new Promise((resolve, reject) => {
        let requestUrl = url + '/ivcs/api/v1/oneTimeToken';
        createRtmpServerTokenWithValidityTime(url, token, validityTime).then((resp) => {
            logWithRequestResponse(requestUrl, resp, null, true);
            if (resp.data && resp.data.token) {
                resolve(resp.data.token);
            } else {
                let response = new IvcsError('4009', logWithRequestResponse(requestUrl, resp, null, false));
                reject(response);
            }
        }).catch((error) => {
            logWithRequestResponse(requestUrl, null, error, true);
            let response = new IvcsError('4009', logWithRequestResponse(requestUrl, null, error, false));
            reject(response);
        });
    });
}

/**
 * 刷新新的token
 * @param {string} backendUrl 访问的url
 * @param {string} userId 用户id
 * @param {string} ticket 登录后返回的ticket
 * @returns Promise.<object, Error>
 */
export async function refreshNewToken(backendUrl, userId, ticket) {
    return await new Promise((resolve, reject) => {
        let para = {
            userId: userId,
            ticket: ticket
        };
        Logger.info('ivcs-js-sdk:request body', para);
        let requestUrl = backendUrl + '/ivcs/api/v1/auth/refresh-token';
        refreshToken(backendUrl, para).then((resp) => {
            logWithRequestResponse(requestUrl, resp, null, true);
            resolve(resp.data);
        }).catch((error) => {
            logWithRequestResponse(requestUrl, null, error, true);
            let response = new IvcsError('400', logWithRequestResponse(requestUrl, null, error, false));
            reject(response);
        });
    });
}

/**
 * 访客登录
 * @param {string} backendUrl 访客url
 * @param {string} name 姓名
 * @param {string} pwd 密码
 * @param {string} org 机构
 * @returns Promise.<object, Error>
 */
export async function customerLogin(backendUrl, name, pwd, org) {
    return await new Promise((resolve, reject) => {
        let para = {
            userName: name,
            pwd: pwd,
            role: "customer",
            org: org
        };
        Logger.info('ivcs-js-sdk:request body', para);
        let requestUrl = backendUrl + '/ivcs/api/v1/auth/logon';
        login(backendUrl, para).then((resp) => {
            logWithRequestResponse(requestUrl, resp, null, true);
            resolve(resp);
        }).catch((error) => {
            logWithRequestResponse(requestUrl, null, error, true);
            let response = new IvcsError('400', logWithRequestResponse(requestUrl, null, error, false));
            reject(response);
        });
    });
}

/**
 * 打印每个网络请求的返回日志
 * @param {string} requestUrl 请求的url
 * @param {object} response   返回值
 * @param {object} error 错误返回
 * @param {boolean} needLog 是否需要打印
 * @returns {string} 日志
 */
export function logWithRequestResponse(requestUrl, response, error, needLog) {
    let message = `time:${new Date()},requestUrl:${requestUrl} `;
    if (response) {
        message = message + `response status:${response.status} `;
        if (response.data && response.data.code) {
            message = message + `code:${response.data.code} `;
        }
        if (isJsonString(response)) {
            message = message + `data:${JSON.stringify(response)}`;
        } else if (response.data && isJsonString(response.data)) {
            message = message + `data:${JSON.stringify(response.data)}`;
        } else if (response.data && response.data.data && isJsonString(response.data.data)) {
            message = message + `data:${JSON.stringify(response.data.data)}`;
        } else if (response.data && response.data.data) {
            let data = response.data.data;
            message = message + `data:` + logObject(data) + ' ';
        } else if (response.data && !response.data.data) {
            let data = response.data;
            message = message + `data:` + logObject(data) + ' ';
        } else if (!isEmptyString(response)) {
            message = message + `data:${response}`;
        }
    }
    if (error) {
        if (isJsonString(error)) {
            message = message + `error:${JSON.stringify(error)}`;
        } else {
            message = message + `error:${error}`;
        }
    }
    needLog && Logger.debug(message);
    return message;
}